#include "texture.h"

using namespace bt;

// Constructors
Texture::Texture() {}

Texture::Texture(Texture& rhs)
{
	*this = rhs;
}

Texture::Texture(const char* filename)
{
	genTexture(filename);
}

Texture::Texture(SDL_Surface* surf)
{
	genTexture(surf);
}

// Assignment operators
Texture& Texture::operator=(Texture& rhs)
{
	texture = rhs.texture;
	dimensions = rhs.getDimensions();
}

// Accessors
GLuint Texture::getTexture() { return texture; }

Vector2f Texture::getDimensions() { return dimensions; }

// Mutators
bool Texture::genTexture(const char* filename)
{
	Uint8* buffer;
	PHYSFS_sint64 filesize = FS_readFile(buffer, filename);
	
	SDL_Surface* surf;
	
	/*
	 * Check if the file loaded and
	 * try to create the surface from the memory
	 */
	if(buffer)
	{
		SDL_RWops* rw = SDL_RWFromMem(buffer, filesize);
		
		surf = IMG_Load_RW(rw, 1);	/* Load surface and release RWops */
	}
	else
	{
		fprintf(stderr, "Unable to load texture from file: %s\n", filename);
		return false;
	}
	
	// Clean up file memory
	delete [] buffer;
	
	
	if(!surf)	/* check that image loaded */
	{
		fprintf(stderr, "Unable to load texture from file: %s\n", filename);
		return false;
	}
	else
		return genTexture(surf); /* Actually attempt to generate texture */
}

bool Texture::genTexture(SDL_Surface* surf)
{
	if(!surf)	/* check that surface is valid */
	{
		fprintf(stderr, "Unable to load texture from surface.\n");
		return false;
	}
	
	dimensions.x = (float)surf->w;
	dimensions.y = (float)surf->h;
	
	// Generate the texture image
	glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf->w, surf->h,
				 0, GL_RGBA, GL_UNSIGNED_BYTE, surf->pixels );
	
	// Filtering
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	
	// Reset GL state
	glMatrixMode(GL_MODELVIEW);
	
	// Free the temporary surface
	SDL_FreeSurface(surf);
	
	return true;
}

// Actions
void Texture::draw()
{
	float qwidth = dimensions.x/2;
	float qheight = dimensions.y/2;
	
	glBindTexture(GL_TEXTURE_2D, texture);
	
	/* Assume GL_MODELVIEW */
	
	glBegin(GL_QUADS);	
		glTexCoord2f(0.0f, 0.0f); /* Bottom Left */
		glVertex3f(-qwidth, -qheight,  0.0f);
		
		glTexCoord2f(1.0f, 0.0f); /* Bottom Right */
		glVertex3f(qwidth, -qheight,  0.0f);
		
		glTexCoord2f(1.0f, 1.0f); /* Top Right */
		glVertex3f(qwidth,  qheight,  0.0f);
		
		glTexCoord2f(0.0f, 1.0f); /* Top Left */
		glVertex3f(-qwidth,  qheight,  0.0f);
	glEnd();
}

void Texture::draw(float posx, float posy)
{
	/*
	 * Use quarter dimensions of the texture to enable
	 * the image to be drawn with origin at top left
	 * but still rotate around the image center
	 */
	float qwidth = dimensions.x/2;
	float qheight = dimensions.y/2;
	
	glBindTexture(GL_TEXTURE_2D, texture);
	
	/* Assume GL_MODELVIEW */
	
	glTranslatef(posx + qwidth, posy + qheight, 0.0f);
	
	glBegin(GL_QUADS);
		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
	
		glTexCoord2f(0.0f, 0.0f); /* Bottom Left */
		glVertex3f(-qwidth, -qheight,  0.0f);
		
		glTexCoord2f(1.0f, 0.0f); /* Bottom Right */
		glVertex3f(qwidth, -qheight,  0.0f);
		
		glTexCoord2f(1.0f, 1.0f); /* Top Right */
		glVertex3f(qwidth,  qheight,  0.0f);
		
		glTexCoord2f(0.0f, 1.0f); /* Top Left */
		glVertex3f(-qwidth,  qheight,  0.0f);
	glEnd();
}

void Texture::freeTexture()
{
	glDeleteTextures(1, &texture);
}
